#include "tsina.h"
#include <iostream>
#include "ufs.h"
using namespace std;
using namespace Facebook;





char Curltools::errorBuffer[CURL_ERROR_SIZE];

Curltools::Curltools()
{

     static bool gi = false;

     if(!gi)
     {
          curl_global_init(CURL_GLOBAL_ALL);
          gi = true;
     }   
     //CURLcode code = curl_global_init(CURL_GLOBAL_DEFAULT);
     //if(code != CURLE_OK)
     //	cout << "curl_init failed, the error code is: "<< code << endl;

     curl = curl_easy_init();
}

Curltools::~Curltools()
{
     if (curl)
          curl_easy_cleanup(curl);
     //curl_global_cleanup();
}

int Curltools::httpCode() const
{
     if (!curl) return 0;

     long http_code;
     if (curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code ) == 0 )
          return http_code;

     return 0;
}


int Curltools::write(char *data, size_t size, size_t nmemb, string* writeData)
{
     if(writeData == NULL)
          return 0;
     int len = size * nmemb;
     writeData->append(data,len);
     return len;

}

string Curltools::postFile(const string& url, const string& content,const string& filename) 
{
     string buffer;

     curl_easy_reset(curl);

     struct curl_httppost* post = NULL;
     struct curl_httppost* last = NULL;

     if(curl_formadd(&post, &last, CURLFORM_COPYNAME, "pic",
                     CURLFORM_FILE, filename.c_str(), CURLFORM_END) != 0
        || curl_formadd(&post, &last, CURLFORM_COPYNAME, "status",
                        CURLFORM_COPYCONTENTS, content.c_str(),	CURLFORM_END) != 0	
          )
     {
          cout << "curl_formadd error.\n";
     }
     else
     {
          curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
          curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
          // curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
          curl_easy_setopt(curl, CURLOPT_HEADER, 0);
          curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
          curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curltools::write);
          curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);

          curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);

          CURLcode code = curl_easy_perform(curl);

          if(code != CURLE_OK)
          {
               cout << "curl_easy_perform failed: "<< code;
               buffer = "";
          }
     }	
     curl_formfree(post);
     return buffer;
}



string Curltools::postDelete(const string& url) 
{
     string buffer;

     curl_easy_reset(curl);
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
     //  curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
//    curl_easy_setopt(curl, CURLOPT_HEADER, 0);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curltools::write);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");

     struct curl_slist* pOAuthHeaderList = NULL;
     string oAuthHttpHeader;
     m_oAuth.getOAuthHeader(eOAuthHttpDelete, url, string(""), oAuthHttpHeader); 
     if( !oAuthHttpHeader.empty() )
     {
          pOAuthHeaderList = curl_slist_append(pOAuthHeaderList, oAuthHttpHeader.c_str());
          if( pOAuthHeaderList )
               curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pOAuthHeaderList);
     }
    
     curl_easy_setopt(curl, CURLOPT_POST, 1);
     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
     CURLcode code = curl_easy_perform(curl);

     if(code != CURLE_OK)
     {
          cout << "curl_easy_perform failed: "<< code;
          buffer = "";
     }

     return buffer;
}

string Curltools::postContent(const string& url, const string& content) 
{
     string buffer;

     curl_easy_reset(curl);

     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
     //    curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
     //    curl_easy_setopt(curl, CURLOPT_HEADER, 0);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curltools::write);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);

     curl_easy_setopt(curl, CURLOPT_POST, 1);

     struct curl_slist* pOAuthHeaderList = NULL;
     string oAuthHttpHeader;
     m_oAuth.getOAuthHeader(eOAuthHttpPost, url, content, oAuthHttpHeader); 
     if( !oAuthHttpHeader.empty() )
     {
          pOAuthHeaderList = curl_slist_append(pOAuthHeaderList, oAuthHttpHeader.c_str());
          if( pOAuthHeaderList )
               curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pOAuthHeaderList);
     }
     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, content.c_str());
     CURLcode code = curl_easy_perform(curl);

     if(code != CURLE_OK)
     {
          cout << "curl_easy_perform failed: "<< code;
          buffer = "";
     }

     if( pOAuthHeaderList )
          curl_slist_free_all( pOAuthHeaderList);

     return buffer;
}


string Curltools::getURL(const string& url)  
{
     string	buffer;

     curl_easy_reset(curl);

     //     const char* a = "jasonyaw:7895123";
     //     if( !isAuthed )
     //     {
     //  curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
     //         isAuthed = true;
     //     }
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
     curl_easy_setopt(curl, CURLOPT_HEADER, 0);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curltools::write);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
//    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "./cookie");

     struct curl_slist* pOAuthHeaderList = NULL;
     string oAuthHttpHeader;
     m_oAuth.getOAuthHeader(eOAuthHttpGet, url, string(""), oAuthHttpHeader); 
     if( !oAuthHttpHeader.empty() )
     {
          pOAuthHeaderList = curl_slist_append(pOAuthHeaderList, oAuthHttpHeader.c_str());
          if( pOAuthHeaderList )
               curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pOAuthHeaderList);
     }

     CURLcode code = curl_easy_perform(curl);

     int http_code =  httpCode() ;
     if(code != CURLE_OK || http_code != 200)
     {
          cout << "curl_easy_perform failed: error_code: " << code << " http_code: " << http_code << "\n";
          buffer.clear();
     }

     if( pOAuthHeaderList )
          curl_slist_free_all( pOAuthHeaderList);

     return buffer;
}


string Curltools::getURL(const string& url, const string& oAuthHttpHeader)
{
     string	buffer;

     curl_easy_reset(curl);

     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
     // curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
     curl_easy_setopt(curl, CURLOPT_HEADER, 0);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curltools::write);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);

     struct curl_slist* pOAuthHeaderList = NULL;
     if( !oAuthHttpHeader.empty() )
     {
          pOAuthHeaderList = curl_slist_append(pOAuthHeaderList, oAuthHttpHeader.c_str());
          if( pOAuthHeaderList )
               curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pOAuthHeaderList);
     }

     CURLcode code = curl_easy_perform(curl);

     if(code != CURLE_OK)
     {
          cout << "curl_easy_perform failed: "<< code;
          buffer = "";
     }
     if( pOAuthHeaderList )
          curl_slist_free_all( pOAuthHeaderList);

     return buffer;
}


bool  Facebook::Curltools::oAuthLogin(const string& consumer_key, const string& consumer_secret, const string &filename)
{
          
     const string request_token_url("http://api.t.sina.com.cn/oauth/request_token");
     setRequestTokenUrl(request_token_url);
     const string authorize_url("http://api.t.sina.com.cn/oauth/authorize");
     setAuthorizeUrl(authorize_url);
     const string access_token_url("http://api.t.sina.com.cn/oauth/access_token");
     setAccessTokenUrl(access_token_url);

     string tmpStr, replyMsg;
     m_oAuth.setConsumerKey(consumer_key);
     m_oAuth.setConsumerSecret(consumer_secret);
     string myOAthAccessTokenKey;
     string myOAthAccessTokenSecret;


               
     ifstream infile(filename.c_str());
     if( infile )
     {
          infile >> myOAthAccessTokenKey >> myOAthAccessTokenSecret;
     }
     infile.close();

     
                    
     /*
       ifstream oAuthTokenKeyIn("token_key.txt");
       ifstream oAuthTokenSecretIn("token_secret.txt");
       if(oAuthTokenKeyIn && oAuthTokenSecretIn)
       {
       oAuthTokenKeyIn >> myOAthAccessTokenKey;
       oAuthTokenSecretIn >> myOAthAccessTokenSecret;
       }
       oAuthTokenKeyIn.close();
       oAuthTokenSecretIn.close();
     */
     if( !myOAthAccessTokenKey.empty() && !myOAthAccessTokenSecret.empty() )
     {
          m_oAuth.setOAuthTokenKey(myOAthAccessTokenKey);
          m_oAuth.setOAuthTokenSecret(myOAthAccessTokenSecret);
     }
     else
     {
          oAuthRequestToken(tmpStr);
          
          cout << "\n Please visit this link in web browser and authorize this application: \n" 
               << tmpStr << endl;
          cout << "Enter the PIN provided by sina: ";
          tmpStr.clear();
          cin >> tmpStr;
          m_oAuth.setOAuthPin(tmpStr);
          oAuthAccessToken();
          m_oAuth.getOAuthTokenKey(myOAthAccessTokenKey);
          m_oAuth.getOAuthTokenSecret(myOAthAccessTokenSecret);
          
          ofstream outfile(filename.c_str());
          outfile << myOAthAccessTokenKey << "\n" << myOAthAccessTokenSecret << endl;
          outfile.close();
     }

     return true;
}

void  Facebook::Curltools::setRequestTokenUrl(const string& request_token_url)
{
     m_request_token_url.assign(request_token_url);
}

void  Facebook::Curltools::setAuthorizeUrl(const string& authorize_url)
{
     m_authorize_url.assign(authorize_url);
}

void Facebook::Curltools::setAccessTokenUrl(const string& access_token_url)
{
     m_access_token_url.assign(access_token_url);
}

bool  Facebook::Curltools::oAuthRequestToken(string& authorizeUrl)
{
     bool ret = false;
     string oAuthHeader;

     if( m_oAuth.getOAuthHeader( eOAuthHttpGet, m_request_token_url, string(""), oAuthHeader) )
     {
               
          string twitterResp = getURL(m_request_token_url, oAuthHeader);
          m_oAuth.extractOAuthTokenKeySecret(twitterResp);
          string oAuthTokenKey;
          m_oAuth.getOAuthTokenKey(oAuthTokenKey);
          authorizeUrl.assign(m_authorize_url);
          authorizeUrl += "?oauth_token=";
          authorizeUrl += oAuthTokenKey;
          ret = true;
     }

     return ret;
}


bool  Facebook::Curltools::oAuthAccessToken()
{
     bool ret = false;
     string oAuthHeader;
     if(m_oAuth.getOAuthHeader(eOAuthHttpGet, m_access_token_url, string(""), oAuthHeader, true ))
     {
          string twitterResp = getURL(m_access_token_url, oAuthHeader);
          cout << "twitterResp=" << twitterResp << "\n";
          m_oAuth.extractOAuthTokenKeySecret(twitterResp);
          ret = true;
     }
     return ret;
}



string Facebook::Curltools::getUrlWithoutAuth(const string& url)
{
     string  buffer;

     curl_easy_reset(curl);

     //curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
     curl_easy_setopt(curl, CURLOPT_HEADER, 0);
     curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curltools::write);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
     //    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "./cookie");

     CURLcode code = curl_easy_perform(curl);

     if(code != CURLE_OK)
     {
          cout << "curl_easy_perform failed: "<< code;
          buffer = "";
     }
     return buffer;
}

